
package pl.lodz.p.browarex.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import pl.lodz.p.browarex.dao.GenericDao;
import pl.lodz.p.browarex.model.Ingredient;
import pl.lodz.p.browarex.model.Product;


@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class ProductServiceImpl implements ProductService<Product, Long> {

	@Autowired
	private GenericDao<Product, Long> productDao;

	@Autowired
	private GenericDao<Ingredient, Long> ingredientDao;

	/*
	 * (non-Javadoc)
	 * 
	 * @see pl.net.beercrm.service.GenericService#upsert(java.lang.Object)
	 */
	@Override
	public void upsert(Product object) {
		List<Product> objectList = findByGuid(object.getProductId());

		if (objectList.size() > 0) {
			Product persistedObject = objectList.get(0);
			persistedObject.setName(object.getName());
			persistedObject.setType(object.getType());
			persistedObject.setCapacity(object.getCapacity());
			persistedObject.setBundle(object.getBundle());
			persistedObject.setVoltage(object.getVoltage());
			persistedObject.setManufacturer(object.getManufacturer());
			persistedObject.setDescription(object.getDescription());
			persistedObject.setPrice(object.getPrice());
			persistedObject.setIngredients(object.getIngredients());
			productDao.update(persistedObject);
		} else {
			productDao.create(object);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pl.net.beercrm.service.GenericService#delete(java.lang.Object)
	 */
	@Override
	public void delete(Product object) {
		List<Product> persistedObjects = findByGuid(object.getProductId());
		for (Product product : persistedObjects) {
			productDao.delete(product);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pl.net.beercrm.service.GenericService#find(java.io.Serializable)
	 */
	@Override
	public Product find(Long id) {
		return productDao.findById(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pl.net.beercrm.service.GenericService#findByGuid(java.lang.String)
	 */
	@Override
	public List<Product> findByGuid(String guid) {
		return productDao.findAllByProperty("productId", guid);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pl.net.beercrm.service.GenericService#list()
	 */
	@Override
	public List<Product> list() {
		return productDao.findAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * pl.net.beercrm.service.ProductService#getIngredients(java.lang.Object)
	 */
	@Override
	public List <Ingredient> getIngredients(Product object) {
		List<Ingredient> resultSet = new ArrayList<Ingredient>(0);
		List<Product> persistedObjects = findByGuid(object.getProductId());

		if (persistedObjects.size() > 0) {
			Product persistedProduct = persistedObjects.get(0);
			resultSet.addAll(persistedProduct.getIngredients());
		}

		return resultSet;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * pl.net.beercrm.service.ProductService#upsertIngredients(java.lang.Object,
	 * java.util.Set)
	 */
	@Override
	public void upsertIngredients(Product object, List<Ingredient> ingredients) {
		List<Product> objects = findByGuid(object.getProductId());

		if (objects.size() > 0) {
			Product persistedObject = findByGuid(object.getProductId()).get(0);
			
			for (Ingredient ingredient : ingredients) {
				List<Ingredient> persistedIngredients = ingredientDao.findAllByProperty("ingredientId", ingredient.getIngredientId());
				if (persistedIngredients.size() > 0) {
					boolean addAmount = true;
					for (Ingredient ingr : persistedIngredients) {
						if (ingr.getAmount() == ingredient.getAmount()) {
							persistedObject.getIngredients().add(ingr);
							ingr.getProducts().add(persistedObject);
							addAmount = false;
						}
					}
					if (addAmount) {
						persistedObject.getIngredients().add(ingredient);
						ingredient.getProducts().add(persistedObject);
						ingredientDao.create(ingredient);
					}
				} else {
					persistedObject.getIngredients().add(ingredient);
					ingredient.getProducts().add(persistedObject);
					ingredientDao.create(ingredient);
				}
			}

			productDao.update(persistedObject);
		}
	}

	/* (non-Javadoc)
	 * @see pl.net.beercrm.service.GenericService#findByProperty(java.lang.String, java.lang.Object)
	 */
	@Override
	public List<Product> findByProperty(String property, Object value) {
		return productDao.findAllByProperty(property, value);
	}

}
